Learn Next.js
hr.icon
1章 Getting Started
npx create-next-app@latest nextjs-dashboard --use-npm --example "https://github.com/vercel/next-learn/tree/main/dashboard/starter-example"
コマンド叩いてベース作成
リモートレポジトリの設定
npm run dev
https://gyazo.com/34b24b15e5e7cfdd725888064c47a0df
ベースプロジェクトの説明
簡単にディレクトリの説明してくれる
感想
scripts/seed.js
Databaseのダミーデータ作成するのか〜。
? 実際、BackendやAPIが別プロジェクトの場合、App Router構成ってどういう開発になるんだろう?
nvmrcで、node v18だけ指定するのね。
/app/lib: 再利用可能なユーティリティ関数やデータ取得関数など、アプリケーションで使用される関数が含まれます。
scriptsが例外的な感じね。
Placeholder Data
知らなかった
TypeScript
ちょこちょこcodeコメントで説明入れてくれているのいいね。
hr.icon
2章 CSS Styling
DOMコピペして、ホットリロードでぱぱっと確認して、クイズ回答
エラー
/app/ui/home.module.cssにcode置いて、/app/page.tsxから、import styles from './home.module.css';
app
ui
home.module.css
page.tsx
うーん、こんな初歩的なミスを最初からする?ドキュメント or ベースプロジェクトが更新されたのかな?
誰もIssueだしてないし、PRだすか。
PR無かったわ。
classの切り替え
知らなかった。利用一般的なの?
? csslassNameとかだけじゃ無理なんだっけ?
クイズ: > Search for "clsx" in your code editor, what components use it to conditionally apply class names?
これ答えなくない?ってなった。
nav-link.tsx内で、clsx無くない?
2個も、最初に怪しい文章があると、本当にこのチュートリアル大丈夫か?ってなっちゃう。
hr.icon
3章 Optimizing Fonts and Images
Font 最適化
import { Inter } from 'next/font/google';
nextのfontライブラリにgoogleフォントがあって、Interというフォントを読み込むらしい
ライブラリとfontが密結合なのね
className={${inter.className}`
export const inter = Inter({ subsets: ['latin'] });
この書き方、なんかうまく動いている感のある説明だけど、Tailwind CSSがもとめるclassプロパティを渡すようにしているのね。 font.ts部分の記述を変えれば、別のfontも利用できる
<AcmeLogo />がfont部分で急に出てきて、なぜここ?となった。
ArrowRightIconいつの間にかimportされているけど、どこで出てきたんだっけ?
言及無かったけど、画面スクショにあったから、Loginリンクのテキスト部分に追加した。
Image 最適化
Image コンポーネントが便利な話
assetは、public以下から読み込んでくれるので、都度importする必要はなく、src部分で指定する。
元画像の拡張子も一緒に書く。
最適化は、Image コンポーネントがいい感じにしてくれる。
hr.icon
4章 Creating Layouts and Pages
Nested routing
各ディレクトリが、pathになっている話
page.tsxが特殊で、該当PageのViewファイルになる。
サンプルだと、ディレクトリ構造むちゃくちゃだね
pageを表すディレクトリとlibやuiがあるのが変な感じ。
ルートの1つ下部分がカオスにならない?
具体
dashboard
lib
ui
page.tsx
One benefit of using layout is that on navigation, only the page components update while the layout won’t re-render. In Next.js, this is called partial rendering:
https://gyazo.com/7add0a7a595307427731ae261f191e53
同じLayoutを当てているページでは、Layoutは再レンダリングされない
どこのレンダリングの話?
Serverでページ生成する時?
Clientでページ生成する時?
headとかメタタグとか、全ページで共有したいもの置きたいよねという話。
hr.icon
5章 Navigating Between Pages
aタグじゃなくてなぜLinkコンポーネントを使うのか?
要件
ユーザーが、Navigation メニューの現在どのページにいるかを視覚化する
実現方法
感想
今回の要件だったら、SSR時に処理できそうだけどね。あとでするのかな?
Automatic code-splitting and prefetching
Next.js はアプリケーションをルート セグメントごとに自動的にコード分割します
初期読み込み時に、jsやCSSが軽くなって嬉しいね。
本番中はいつでも、<Link>コンポーネントがブラウザのビューポートに表示されると、Next.js がリンクされたルートのコードをバックグラウンドで自動的にプリフェッチします
SSR?している時ってどうなるんだろう?
そもそも、従来のSSRと考え方が違うのか?
hr.icon
6章 Setting Up Your Database
Setup GitHub
Setup Vercel
お金に厳しい印象あるけど
今回Databaseがメインじゃないからいいんだけど、Vercelに寄っているなぁと実感する。
env
? env.localは、したがってコピペしたけど、他の環境はどうするんだっけ?
all Vercelだから気にしなくていいんだっけ?
最後に、npm i @vercel/postgresターミナルで実行して Vercel Postgres SDK をインストールします。
もう、Project設定時にセットアップされているんだよなぁ
npm run seedでエラー
? なんでだ?: node.jsが若干古いから?どこかでおかしくなった?
正解だった。node.js v18が若干古くて警告でていたので、いっそのことLTSのv20にしたら解決した。
seedしたDataをVercel Storageで確認
DataのBrowseの検索部分に触れないとData出てこないの、分からなかった。
https://gyazo.com/cae129714356d96d3bb02d88199ecb25
クエリは、Next.js関係ないけどね
hr.icon
7章 Fetching Data
Choosing how to fetch data
データの取得方法が色々あるとのこと
API は、アプリケーション コードとデータベースの間の中間層
clientのscriptから叩く場合
serverで、SSGする時に事前に叩く場合もある。
Databaseを操作するBackendがNext.jsじゃない時とか
FEの関心事が減る意味ではいいんだけど
Database queries
フルスタック アプリケーションを作成する場合は、データベースと対話するロジックも作成する必要があります
Using Server Components to fetch data
各clientで繰り返すfetchをserver側で1回にできるのはいいね
Server Components support promises, providing a simpler solution for asynchronous tasks like data fetching. You can use async/await syntax without reaching out for useEffect, useState or data fetching libraries.
あまり理解しきれなかった。もう少し分解したい。
Using SQL
簡単に使えるねという確認
Fetching data for the dashboard overview page
ページは非同期コンポーネントです。
export default async function Page() {のasync定義しているから、awaitできるねってことか。
<RevenueChart/>の描画
fetch関数のimport、fetchの実行、<RevenueChart/>にデータ渡す、<RevenueChart/>内のコメントも解除
<LatestInvoices>の描画
修正箇所のハイライト一部足りないね。
<Card>の描画
データ リクエストは意図せずに相互にブロックし、リクエスト ウォーターフォールを作成します。
? どうやってウォーターフォール認知するんだろう?
デフォルトでは、Next.js はパフォーマンスを向上させるためにルートを事前レンダリングします。これは静的レンダリングと呼ばれます。したがって、データが変更されても、ダッシュボードには反映されません。
? ユーザーの操作で変更操作入った場合も、事前レンダリング再実行しないといけないということ?
What are request waterfalls?
https://gyazo.com/730bd4de2914353b53a0ff63a16ca817
各リクエストに依存関係があれば、リクエスト待っても良いんだけど、意図的ではないので、パフォーマンスに影響がある。
Parallel data fetching
request waterfallsのパフォーマンス課題の解消。
JSのPromise.all()使えば、すべての Promise を同時に開始できる
この JavaScript パターンの使用には欠点
1 つのデータ リクエストが他のすべてのデータリクエストよりも遅い場合はどうなるでしょうか。
他の早いリクエストが待たされるのもったいないね。
hr.icon
8章 Static and Dynamic Rendering
Fetch周りの課題
data requestにより、意図しないウォーターフォールが発生
Static Pageに、Dynamicなデータの更新はアプリケーションに反映されない
What is Static Rendering?
https://gyazo.com/210230028550418adc96ffeab4141e72
With static rendering, data fetching and rendering happens on the server at build time (when you deploy) or during revalidation. The result can then be distributed and cached (stored) in a Content Delivery Network (CDN).
? Vercelの話じゃないの?他のCloudでもさくっとできるの?
Good: 更新されないUIやページ
Bad: 定期的に更新されるページ
ユーザーごとに違ったり、操作でデータが変わったりする箇所
What is Dynamic Rendering?
頻繁に更新されるデータを利用する箇所にはぴったり
ユーザーの操作に基づいてデータが更新、ページレンダリングされる
リクエスト時の情報利用
感想:
これ結構考えることありそう。自分がRails上でフロントエンド実装している際にもかなり利用しているけど、どこでその情報を扱うか考えたい。
ふと思ったこと
でかいサービスだと、パフォーマンスチューニングをお金で語れそうなのがいいね。
Making the dashboard dynamic
? noStore()ってなんだ?
サーバー コンポーネント内で呼び出される Next.js APIunstable_noStoreまたはデータ取得関数を使用して、静的レンダリングをオプトアウトできます
// Add noStore() here prevent the response from being cached.
fetch時に、デフォルトがキャッシュ利用するけど、それを無効化するということっぽい
Simulating a Slow Data Fetch
遅いFetchの実演
hr.icon
9章 Streaming
What is streaming?
こっちに寄せた。
Next.js でストリーミングを実装する方法は 2 つ
Streaming a whole page with loading.tsx
抽象化しすぎてmagicだなぁ
https://gyazo.com/f292b5558d9dab14a12572274ac0372c
<Sidebar>は静的であるため、すぐに表示されます。<Sidebar>ユーザーは、動的コンテンツの読み込み中に対話できます。
Adding loading skeletons
事前に用意されているskeltonを渡すだけ。
Fixing the loading skeleton bug with route groups
(overview)ディレクトリを用意して、page.tsxとloading.tsxを入れると、他のページに反映されなくなる。
Streaming a component
アプリケーションのレンダリング部分を延期することもできる
ざっくり
Streamingしたいcomponentを、Suspenseで包み、loading component渡す
Streamingしたいcomponent内で、fetchする
サンプルcode上で言及されていないけど、
const revenue = await fetchRevenue();の削除忘れずに
RevenueChartの引数周りの修正も忘れずに
https://gyazo.com/25e2254ea575a42eeb17454aea772e40
グラフ部分がStramingされていることがわかる。
すごい
Practice: Streaming <LatestInvoices>
それぞれのcomponentが、読み込み完了次第レンダリングされる。
Grouping components
Cardの場合、視覚的に不快なa popping effectが起きる可能性がある。
? どんなエフェクトのことだろう。
高速読み込みでバタバタすること?CLSのこと?
Card4つはWrappして、Suspenceすることで一緒に描画される。
Suspence4つ分けると、それぞれパタパタ動く。
感想
Page componentやstateにfetchしたデータをまとめて流すのが主流だったけど、componentでfetchするって感じだなぁ
Deciding where to place your Suspense boundaries
どのコンテンツを優先して表示したいか?
心配しないで。正しい答えは無いよ
感想: 都度あるべきを考えればいいし、後で、より良くできるという選択肢があるのが良いね。
今まではそんな細かく、気軽にチューニング出来なかったわけで...
hr.icon
10章 Partial Prerendering (Optional)
Combining Static and Dynamic Content
ほとんどのルートは完全に静的または動的ではありません。
例:
ソーシャル メディア フィード
e コマース サイト
物件メディア
What is Partial Prerendering?
https://gyazo.com/1510c4eb44866d9a506c51b413780293
イメージしやすい図。
How does Partial Prerendering work?
The fallback is embedded into the initial static file along with other static content. At build time (or during revalidation), the static parts of the route are prerendered, and the rest is postponed until the user requests the route.
It's worth noting that wrapping a component in Suspense doesn't make the component itself dynamic (remember you used unstable_noStore to achieve this behavior), but rather Suspense is used as a boundary between the static and dynamic parts of your route.
The great thing about Partial Prerendering is that you don't need to change your code to use it. As long as you're using Suspense to wrap the dynamic parts of your route, Next.js will know which parts of your route are static and which are dynamic.
ここ重くて読みきれない。
hr.icon
11章 Adding Search and Pagination
Starting code
用意してくれているcodeをコピペして読む
Why use URL search params?
補足
デメリットもあって、ちゃんと設計しないと、とクエリパラメータ変更すると壊れたり、配慮が必要な点が注意
感想
今、railsベースのFrontend実装しているから、分かりみが深い。あと、他メンバーも理解しやすそうで良い。
Adding the search functionality
Next.js client hooks
use-debounce
Adding pagination
ページネーションの動的にURL生成
TotalPageをpropで渡すのなぜ?
ページネーションのループ処理に利用
矢印部分のdisableに利用
全体感
file上にuse clientとか書いてるとまぁ分かるけど、ブラウザ上だと分かんなくなる
hr.icon
12章 Mutating Data
感想
form action何となくで使っているけど、action属性詳しく理解していないなぁ
サーバー アクションを使用する利点は何ですか?
? どういうこと?
Creating an invoice
? Backendは、別サーバーの場合どういう使い方いい?
clientから、API直接叩く?
パフォーマンスを考えると、同じサーバーで叩いた方が通信的にいいんだろうけど、もともとのAPI資産利用したいとか実装担当者の関心事分離させたいとかでよくありそう。
Deleteボタン単体にForm属性で囲んでいる。
何か、簡易なAPIって感じだ。
補足
invoice={invoice} で型エラーが出ているが、13章で存在チェック入って解決するので気にしないこと。
hr.icon
13章 Handling Errors
Adding try/catch to Server Actions
ここは、普通のAPI作る時のエラーキャッチの話。
Handling all errors with error.tsx
あれば、errorより優先されて使われる。
ファイルのimport指定は行わず、import { notFound } from 'next/navigation';して、存在チェック処理書いて表示する。
hr.icon
14章 Improving Accessibility
チュートリアルには無いけれど、Linterの設定はもともとないから、eslintコマンド実行すると初期設定される。
最近、修正されたっぽいので、修正以降にスタートした人は問題なさそう。
該当プラグインのinstall
npm install eslint-plugin-jsx-a11y --save-dev
configの作成と追加
自身のローカルになければ、作る
code:.eslintrc.json
{
}
linterエラーでない?
alt={${invoice.name}'s profile picture}をすでに書いていた。
該当削除試しに、消すとエラーが起きる
Improving form accessibility
サーバー上のフォームを検証する
? use client使っているのに、serverなのか?
Zodでform validation分かりやすくていいな actions.ts色々あって、どのあたりに書けばいいんだっけ?となる。
特にファイルの行数とサンプルcode例の行数が違うため。
createInvoiceの最終修正差分助かる。
? prevState利用されていないとなっているけどいいんだっけ?
TS及び、Editorが色々エラーを伝えてくれるからやっぱりいいな。
変なデバッグやデータチェックする必要無いのが最高
formのエラーメッセージなど、サンプルコード真似るだけだと全て修正されないので、テキスト読んだり見様見真似で修正すること。
分からなければ、サンプルコードの最終版参考にすること
form component共通化してぇ
hr.icon
15章 Adding Authentication
ユーザーが本人であるかどうかをシステムがチェックする方法です。
Creating the login route
route作って、コピペ
手動で実装することもできるが、時間がかかり、エラーが発生しやすくなる。
チュートリアルではベータ版だけど、最新版インストールしてもいいと思う。
いや、だめだった。
後々いろんな箇所でエラーでた。
betaであるv5じゃないとだめっぽい?
code: ex.auth.ts
Credentials({
credentials: {},
何か、型がないと言われたのでCopilotくんといっしょに考えて追加した。
hr.icon
16章 Adding Metadata
Config-based
layoutやpageでmetadataのobjectや関数を利用
File-based
該当するファイルネームのファイルを作れば自動で対応してくれる。
Favicon and Open Graph image
public/からapp/にファイルを移動させると自動で対応される例
というか、public/以下にないけどね。
export const metadata: Metadata書くだけで判別してくれるのね
hr.icon
終わり
感想
難しいところは一旦コピペするなりして理解掴んでもらったらと思う。
一部、足りないファイルやcodeももあったけど、今は直っているっぽい